package com.softserveinc.fragments.adapter;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.TextView;

import com.softserveinc.MovieManagerApplication;
import com.softserveinc.R;
import com.softserveinc.data.MovieDataManager;
import com.softserveinc.data.MovieDataManager.PageableMovieListCallBack;
import com.softserveinc.data.help.MovieListType;
import com.softserveinc.model.Movie;

public class MovieListAdapter extends ArrayAdapter<Movie> implements
		MovieDataManager.MoviePosterCallBack {

	private static final String TAG = MovieListAdapter.class.getSimpleName();

	private static final int NORMALIZE_VALUE = 2;
	private static final String N_A = "n/a";
	private static final String DATE_FORMAT = "dd-MM-yyyy";

	private final OnScrollListener scrollListener = new MovieListScrollListemer();

	private final PageableMovieListCallBack pageableCallBack;

	private final MovieManagerApplication application;

	private final MovieListType movieListType;

	private boolean canRecycle = false;

	public MovieListAdapter(final Context context,
			final int textViewResourceId, final List<Movie> movies,
			final PageableMovieListCallBack pageableCallBack,
			final MovieListType movieListType) {
		super(context, R.layout.movie_row, R.id.value_movie_title_in_row,
				movies);

		this.pageableCallBack = pageableCallBack;
		this.movieListType = movieListType;

		application = (MovieManagerApplication) context.getApplicationContext();
	}

	@Override
	public View getView(final int position, final View convertView,
			final ViewGroup parent) {
		Log.e(TAG, "get view " + position);

		View view = super.getView(position, convertView, parent);

		Movie movie = getItem(position);

		setPoster(view, movie);

		setCertification(view, movie);

		setRealeseDate(view, movie);

		setRatingBar(view, movie);

		return view;
	}

	private void setPoster(final View view, final Movie movie) {
		ImageView poster = (ImageView) view.findViewById(R.id.icon_poster);

		ProgressBar progressBar = (ProgressBar) view
				.findViewById(R.id.icon_poster_progress_bar);

		try {
			if (movie.getPoster() != null && !movie.getPoster().isRecycled()) {
				if (canRecycle) {
					poster.setVisibility(View.GONE);
					movie.getPoster().recycle();
					progressBar.setVisibility(View.VISIBLE);
				} else {
					poster.setVisibility(View.VISIBLE);
					poster.setImageBitmap(movie.getPoster());
					progressBar.setVisibility(View.GONE);
				}

			} else {
				poster.setVisibility(View.GONE);
				progressBar.setVisibility(View.VISIBLE);
			}
		} catch (Exception e) {
			Log.e(TAG, "this will never be caught", e);
		}
	}

	private void setCertification(final View view, final Movie movie) {
		ImageView certification = (ImageView) view
				.findViewById(R.id.icon_restriction);
		certification.setImageResource(movie.getCertification()
				.getValidIconID());
	}

	private void setRatingBar(final View view, final Movie movie) {
		RatingBar ratingBar = (RatingBar) view
				.findViewById(R.id.rating_bar_movie);
		Double popularity = movie.getPopularity();

		if (popularity == null) {
			popularity = 0.;
		}

		ratingBar.setRating(popularity.floatValue() / NORMALIZE_VALUE);
		ratingBar.setFocusable(false);
		ratingBar.setEnabled(false);
	}

	private void setRealeseDate(final View view, final Movie movie) {
		TextView releaseDateText = (TextView) view
				.findViewById(R.id.value_release_date_in_row);

		SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
		Date releaseDate = movie.getReleaseDate();
		if (releaseDate == null || releaseDate.getYear() == 1900) {
			releaseDateText.setText(N_A);
		} else {
			releaseDateText.setText(format.format(releaseDate));
		}
	}

	public OnScrollListener getScrollListener() {
		return scrollListener;
	}

	@Override
	public void posterLoaded() {
		notifyDataSetChanged();
	}

	private class MovieListScrollListemer implements OnScrollListener {

		private boolean nonScrolled = true;

		@Override
		public void onScrollStateChanged(final AbsListView view,
				final int scrollState) {

			switch (scrollState) {
			case SCROLL_STATE_IDLE:
				MovieListAdapter.this.canRecycle = false;

				validateImages(view);

				if (pageableCallBack != null
						&& view.getLastVisiblePosition() == getCount()) {
					loadMoreMovies(view);
				}

				break;
			case SCROLL_STATE_TOUCH_SCROLL:
				MovieListAdapter.this.canRecycle = true;

				application.getDataManager().interruptLoadingPosters(
						MovieListAdapter.this);
				break;
			case SCROLL_STATE_FLING:
				MovieListAdapter.this.canRecycle = true;
				break;
			}
		}

		@Override
		public void onScroll(final AbsListView view,
				final int firstVisibleItem, final int visibleItemCount,
				final int totalItemCount) {
			if (nonScrolled && view.getLastVisiblePosition() > 0) {

				nonScrolled = false;

				validateImages(view);
				return;
			}
		}

		private void loadMoreMovies(final AbsListView view) {
			int lastPosition = view.getLastVisiblePosition();
			if (lastPosition >= MovieDataManager.MAX_MOVIE_LIST_SIZE
					|| !application.getHardwareManager().isNetworkConnected()) {
				pageableCallBack.restrictLoading();
			} else {
				int currentPage = lastPosition / MovieDataManager.PAGE_SIZE;

				int nextPage = ++currentPage;

				application.getDataManager().manageDataForMovieList(
						pageableCallBack, movieListType, nextPage);
			}
		}

		private void validateImages(final AbsListView view) {
			List<Movie> movies = new ArrayList<Movie>();

			int first = view.getFirstVisiblePosition();
			int last = view.getLastVisiblePosition();

			for (int i = first; i <= last; i++) {
				if (i == getCount()) {
					break;
				}

				Movie movie = getItem(i);

				if (movie.getPoster() == null || movie.getPoster().isRecycled()) {
					movies.add(movie);
				}
			}

			application.getDataManager().manageDataForMovieListImages(movies,
					MovieListAdapter.this);
		}
	}
}
